#
# Copyright (c) 2008 Open Kernel Labs, Inc. (Copyright Holder).
# All rights reserved.
# 
# 1. Redistribution and use of OKL4 (Software) in source and binary
# forms, with or without modification, are permitted provided that the
# following conditions are met:
# 
#     (a) Redistributions of source code must retain this clause 1
#         (including paragraphs (a), (b) and (c)), clause 2 and clause 3
#         (Licence Terms) and the above copyright notice.
# 
#     (b) Redistributions in binary form must reproduce the above
#         copyright notice and the Licence Terms in the documentation and/or
#         other materials provided with the distribution.
# 
#     (c) Redistributions in any form must be accompanied by information on
#         how to obtain complete source code for:
#        (i) the Software; and
#        (ii) all accompanying software that uses (or is intended to
#        use) the Software whether directly or indirectly.  Such source
#        code must:
#        (iii) either be included in the distribution or be available
#        for no more than the cost of distribution plus a nominal fee;
#        and
#        (iv) be licensed by each relevant holder of copyright under
#        either the Licence Terms (with an appropriate copyright notice)
#        or the terms of a licence which is approved by the Open Source
#        Initative.  For an executable file, "complete source code"
#        means the source code for all modules it contains and includes
#        associated build and other files reasonably required to produce
#        the executable.
# 
# 2. THIS SOFTWARE IS PROVIDED ``AS IS'' AND, TO THE EXTENT PERMITTED BY
# LAW, ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED.  WHERE ANY WARRANTY IS
# IMPLIED AND IS PREVENTED BY LAW FROM BEING DISCLAIMED THEN TO THE
# EXTENT PERMISSIBLE BY LAW: (A) THE WARRANTY IS READ DOWN IN FAVOUR OF
# THE COPYRIGHT HOLDER (AND, IN THE CASE OF A PARTICIPANT, THAT
# PARTICIPANT) AND (B) ANY LIMITATIONS PERMITTED BY LAW (INCLUDING AS TO
# THE EXTENT OF THE WARRANTY AND THE REMEDIES AVAILABLE IN THE EVENT OF
# BREACH) ARE DEEMED PART OF THIS LICENCE IN A FORM MOST FAVOURABLE TO
# THE COPYRIGHT HOLDER (AND, IN THE CASE OF A PARTICIPANT, THAT
# PARTICIPANT). IN THE LICENCE TERMS, "PARTICIPANT" INCLUDES EVERY
# PERSON WHO HAS CONTRIBUTED TO THE SOFTWARE OR WHO HAS BEEN INVOLVED IN
# THE DISTRIBUTION OR DISSEMINATION OF THE SOFTWARE.
# 
# 3. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY OTHER PARTICIPANT BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

Import("env", "args", "conf", "UserError")
import os

# Determine if we are using user mutexes or kernel mutexes and setup
# main source files appropriately.
mutex_type = args.get("MUTEX_TYPE", "user").lower()

source = ["src/count_lock.c", "src/count_trylock.c", "src/count_unlock.c"];
## @todo FIXME: Check argument system is supported by library - awiggins.
source_kernel_shared = ["src/sys-%s/*.c" % args["system"]]
source_kernel_only = ["src/kernel_lock.c", "src/kernel_trylock.c",
                      "src/kernel_unlock.c"];
source_hybrid = ["src/hybrid_lock.c", "src/hybrid_trylock.c",
                 "src/hybrid_unlock.c"]
source_user = ["src/user_init.c", "src/user_free.c", "src/user_unlock.c"]
source_user_atomic = ["src/user_lock.c", "src/user_trylock.c"]

if (mutex_type == "hybrid"):
    #hybrid source is pulled in below (first checks if arch-specific hybrid exists
    source += source_kernel_shared
    env.Append(CPPDEFINES = [("CONFIG_HYBRID_MUTEXES", 1)])
elif (mutex_type == "kernel"):
    source += source_kernel_shared + source_kernel_only
    env.Append(CPPDEFINES = [("CONFIG_KERNEL_MUTEXES", 1)])
elif (mutex_type == "user"):
    source += source_user + source_user_atomic
    env.Append(CPPDEFINES = [("CONFIG_USER_MUTEXES", 1)])
elif (mutex_type == "user_arch"):
    source += source_user
    env.Append(CPPDEFINES = [("CONFIG_USER_MUTEXES", 1)])
else:
    raise UserError, \
        "'mutex_type' must be one of 'hybrid', 'kernel', 'user', or 'user_arch'."

# Setup public headeres
public_headers = [("include/", "include/%(name)s/")]

# Set up dependancies on other libraries.
libs = ["atomic_ops"]

# For mutex_type = user_arch or hybrid, set up architecture-specific source files.
# arch files should be in arch/libs/mutex/src/{mutex_type}/
if (mutex_type == "user_arch" or mutex_type == 'hybrid'):
    # Search for architecture-specific files.
    src_root = Dir('#').srcnode().abspath
    arch = env.machine.arch
    arch_path = os.path.join('arch', arch, args['package'], "src", mutex_type)
    if mutex_type == "user_arch":
        possible_arch_path = os.path.join('arch', arch, args['package'], "src")
        if os.path.exists(os.path.join(src_root, possible_arch_path)):
            arch_path = possible_arch_path
        possible_arch_path = \
                           os.path.join("cust", args["cust"], "arch", arch, args["package"], "src")
        if os.path.exists(os.path.join(src_root, possible_arch_path)):
            arch_path = possible_arch_path
    possible_arch_path = \
        os.path.join("cust", args["cust"], "arch", arch, args["package"], "src", mutex_type)
    if os.path.exists(os.path.join(src_root, possible_arch_path)):
        arch_path = possible_arch_path

    # If there are no files and we are user_arch, throw an error.
    # otherwise, if we are hybrid, include the arch-independent hybrid source
    if not os.path.exists(os.path.join(src_root, arch_path)):
        if mutex_type == "user_arch":
            raise UserError, \
                  "Architecture '%s' is not supported by libmutex." % (arch)
        elif mutex_type == "hybrid":
            source += source_hybrid

    else:
        # Add files to the sources list
        arch_path = "#" + arch_path
        source += [arch_path + "/*.c", arch_path + "/*.spp"]
        public_headers += [(arch_path + "/include/", "include/%(name)s/arch/")]

# Setup unit tests if required.
if "mutex" in env.test_libs:
    source.append("test/*.c")
    public_headers.append(("test/", "include/%(name)s/"))

# Return the library object.
lib = env.KengeLibrary("mutex", source=source, public_headers=public_headers, \
                           LIBS=libs)
Return("lib")

